package org.databasefacade.statements;

import java.util.ArrayList;

import org.databasefacade.select.Comparison;
import org.databasefacade.select.Condition;
import org.databasefacade.select.From;
import org.databasefacade.select.GroupBy;
import org.databasefacade.select.Having;
import org.databasefacade.select.Join;
import org.databasefacade.select.OrderBy;
import org.databasefacade.select.Select;
import org.databasefacade.select.Where;
import org.databasefacade.table.Table;
import org.databasefacade.translator.Translator;

public class SelectStatement implements DatabaseStatement  {
	private From from;
	private Where where = new Where();
	private Having having = new Having();
	private Select select;
	private GroupBy groupBy = new GroupBy();
	private OrderBy orderBy = new OrderBy();
	private ArrayList unions = new ArrayList();
	private ArrayList unionWith = new ArrayList();
	private Translator translator;
	

	public SelectStatement(Table table) {
		this.translator = table.getDBHelper().getTranslator();
		from = new From(table);
		select = new Select(table.getDBHelper().getTranslator());
	}

	
	public SelectStatement(Table table, boolean selectAllColumns) {
		this.translator = table.getDBHelper().getTranslator();
		select = new Select(table.getDBHelper().getTranslator());
		select.allTableColumns(table);
		from = new From(table);
		select =  new Select(table.getDBHelper().getTranslator());
	}
	
	
	
	/**
	 * Use this method to access the fields that must be selected
	 */
	public Select select() {
		return select;
	}
	
	/**
	 * Use this method to set from clause
	 */
	public From from() {
		return from;
	}
	
	/**
	 * Use this method to set where clause
	 */
	public Condition where(Comparison compare) {
		where.first(compare);
		return where.conditions();
	}
	public Condition where() {
		return where.conditions();
	}
	
	/**
	 * Use this method to set group by clause
	 */
	public GroupBy groupBy() {
		return groupBy;
	}

	
	/**
	 * Use this method to set having clause
	 */
	public Having having() {
		return having;
	}
	
	/**
	 * Use this method to set order by clause
	 */
	public OrderBy orderBy() {
		return orderBy;
	}
	
	/**
	 * Union statements
	 */
	public void addUnion(SelectStatement sel) {
		unions.add(sel);
		unionWith.add("UNION");
	}
	public void addUnionAll(SelectStatement sel) {
		unions.add(sel);
		unionWith.add("UNION ALL");
	}
	
	/**
	 * Return the generated SQL for this statement
	 */
	public String getSQL() {
		String from_plus_where = from.getSQL() + where.getSQL();
		if ( translator.getJoinNotationMode() == Join.NATIVE_NOTATION ) {
			from_plus_where = translator.buildNativeFromSQL(from, where) + " " + 
								translator.buildNativeWhereSQL(from, where);
		} 
		select.assignGroupBy(groupBy);
		String sql = select.getSQL() + "\n  " + from_plus_where + groupBy.getSQL() + orderBy.getSQL();
		return sql;
	}
	

}
